/*
 * Copyright 2004-2008 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
Spring = {};

Spring.debug = true;
		
Spring.decorations = {};

Spring.decorations.applied = false;

Spring.asyncValidations = {};

Spring.asyncValidations.applied = false;

Spring.initialize = function(){
	// first wrap native handlers with async validations
	Spring.applyAsyncValidations();
	// then apply decorations to elements
	Spring.applyDecorations();
};

Spring.addAsyncValidation = function(validation){
	/* only one async validation per element is permitted */
	Spring.asyncValidations[validation.elementId] = validation;
	if(Spring.asyncValidations.applied) {
		validation.apply();
	}
};

Spring.addDecoration = function(decoration){
	/* decide if decorations object already has decoration under this hash key 
	 * (id of the element, to which decoration will be applied), if not, create new array under key 
	 * (elementId) and push decoration to this array */
	if (!Spring.decorations[decoration.elementId]) {
		Spring.decorations[decoration.elementId] = [];
		Spring.decorations[decoration.elementId].push(decoration);
	} else {
		var replaced = false;
		/* element with given elementId already has some decoration(decorations) on it,
		 * if iterate over all of them, and if one is the same type (declared class) 
		 * as decoration to be applied, invoke cleanup() function on it, and replace 
		 * it with given decoration, otherwise add new decoration to array */
		for(var i = 0; i<Spring.decorations[decoration.elementId].length; i++) {
			var existingDecoration = Spring.decorations[decoration.elementId][i];
			if(existingDecoration.equals(decoration)) {
				if (existingDecoration.cleanup != undefined) {
					existingDecoration.cleanup();
				}
				Spring.decorations[decoration.elementId][i] = decoration;
				replaced=true;
				break;
			}
		}
		if (!replaced) {
			Spring.decorations[decoration.elementId].push(decoration);
		}
	}
	
	if(Spring.decorations.applied) {
		decoration.apply();
	}
};
		
Spring.applyAsyncValidations = function() {
	if (!Spring.asyncValidations.applied) {
		for (var elementId in Spring.asyncValidations) {
			if (Spring.asyncValidations[elementId] !== false) {
				Spring.asyncValidations[elementId].apply();					
			}
		}
		Spring.asyncValidations.applied = true;		
	}
};

Spring.applyDecorations = function(){
	if (!Spring.decorations.applied) {
		for (var elementId in Spring.decorations) {
			for (var x = 0; x < Spring.decorations[elementId].length; x++) {
				Spring.decorations[elementId][x].apply();
			}
		}
		Spring.decorations.applied = true;
	}
};

Spring.validateAll = function(){
	var valid = true;
	for (var elementId in Spring.decorations) {
		for (var x = 0; x < Spring.decorations[elementId].length; x++) {
			if (Spring.decorations[elementId][x].widget && !Spring.decorations[elementId][x].validate()) {
				valid = false;
			}
		}
	}
	return valid;
};

Spring.validateRequired = function(){
	var valid = true;
	for (var elementId in Spring.decorations) {
		for (var x = 0; x < Spring.decorations[elementId].length; x++) {
			if (Spring.decorations[elementId][x].widget && Spring.decorations[elementId][x].isRequired() && 
			!Spring.decorations[elementId][x].validate()) {
				valid = false;
			}
		}
	}
	return valid;
};

Spring.AbstractElementDecoration = function(){};

Spring.AbstractElementDecoration.prototype = {
	
	elementId : "",
	widgetType : "",
	widgetModule : "",
	widget : null,
	widgetAttrs : {},
	
	apply : function(){},
	
	validate : function(){},
	
	isRequired : function(){},
	
	equals : function(/*Object*/other){}
};

Spring.AbstractValidateAllDecoration = function(){};

Spring.AbstractValidateAllDecoration.prototype = {
	
	event : "",
	elementId : "",
	
	apply : function() {},
	
	cleanup : function(){},
	
	handleEvent : function(event){},
	
	equals : function(/*Object*/other){}
};

Spring.AbstractAsyncValidation = function(){};

Spring.AbstractAsyncValidation.prototype = {
		
	url : "",
	method : "",
	event : "",
	elementId : "",
	
	apply : function() {},
	
	handleEvent : function(event){}
};

require(["dojo/domReady!"], Spring.initialize);



